﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ifunction.Twilio
{
    /// <summary>
    /// Class SMSMessage.
    /// </summary>
    [DataContract]
    [KnownType(typeof(MessagingStatus))]
    public class Message
    {
        #region Property

        /// <summary>
        /// Gets the key.
        /// </summary>
        /// <value>The key.</value>
        [DataMember]
        public Guid Key { get; set; }

        [DataMember]
        public string Sid { get; set; }

        /// <summary>
        /// Gets or sets the media URI.
        /// </summary>
        /// <value>The media URI.</value>
        [DataMember(Name = "Uri")]
        public Uri MediaUri { get; set; }

        /// <summary>
        /// Gets or sets from number.
        /// </summary>
        /// <value>From number.
        /// <example>
        /// US number: +1 (201) 16546817
        /// Value: +12016546817
        /// CN number: +86 13312523215
        /// Value: +8613312523215
        /// </example>
        /// </value>
        [DataMember(Name = "From")]
        public string FromNumber { get; set; }

        /// <summary>
        /// Gets or sets the To number.
        /// </summary>
        /// <value>To number.
        /// <example>
        /// US number: +1 (201) 16546817
        /// Value: +12016546817
        /// CN number: +86 13312523215
        /// Value: +8613312523215
        /// </example>
        /// </value>
        [DataMember(Name = "To")]
        public string ToNumber { get; set; }

        /// <summary>
        /// Gets or sets the body.
        /// </summary>
        /// <value>The body.</value>
        [DataMember]
        public string Body { get; set; }

        /// <summary>
        /// Gets or sets the state.
        /// </summary>
        /// <value>The state.</value>
        [DataMember]
        public MessagingStatus Status { get; set; }

        [DataMember]
        public DateTime CreatedStamp { get; set; }

        #endregion

        #region Constuctor

        /// <summary>
        /// Initializes a new instance of the <see cref="Message"/> class.
        /// </summary>
        /// <param name="createdStamp">The created stamp.</param>
        public Message(DateTime createdStamp)
        {
            this.CreatedStamp = createdStamp;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Message"/> class.
        /// </summary>
        public Message()
            : this(DateTime.UtcNow)
        {

        }

        #endregion

        /// <summary>
        /// Formats the phone number.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns>System.String.</returns>
        protected string FormatPhoneNumber(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                input = string.Empty;
            }
            else
            {
                input = input.Replace(" ", string.Empty);
                if (!input.StartsWith("+"))
                {
                    input = "+" + input;
                }
            }

            return input;
        }

        #region Validate

        /// <summary>
        /// The phone number regex
        /// </summary>
        protected static Regex PhoneNumberRegex = new Regex(
            @"\+[0-9]{5,}"
            , RegexOptions.Compiled);

        /// <summary>
        /// Validates this instance.
        /// </summary>
        /// <exception cref="InvalidObjectException">
        /// SenderNumber;null
        /// or
        /// TargetNumber;null
        /// </exception>
        public void Validate()
        {
            this.FromNumber = this.FormatPhoneNumber(this.ToNumber);
            this.ToNumber = this.FormatPhoneNumber(this.ToNumber);

            if (!PhoneNumberRegex.IsMatch(this.FromNumber))
            {
                throw new InvalidCastException("SenderNumber");
            }

            if (!PhoneNumberRegex.IsMatch(this.ToNumber))
            {
                throw new InvalidCastException("TargetNumber");
            }
        }

        #endregion
    }
}
